🧪 mazda: relay stock LKAS and lane alerts - #2
Closed
mzdnick wants to merge 12 commits into
Closed
Conversation
There was a problem hiding this comment.
Thanks for contributing to opendbc! In order for us to review your PR as quickly as possible, check the following:
- Convert your PR to a draft unless it's ready to review
- Read the contributing docs
- Before marking as "ready for review", ensure:
- the goal is clearly stated in the description
- all the tests are passing
- include a route or your device' dongle ID if relevant
mzdnick
marked this pull request as draft
August 22, 2026 08:28
mzdnick
force-pushed
the
mazda-stock-lkas-relay
branch
from
August 22, 2026 09:04
51abe8a to
1db28d0
Compare
The rebuilt CAM_LANEINFO decoded and re-encoded the camera's frame through a DBC that describes 24 of its 64 bits, so 41 bits -- all of byte 2 among them -- went out as zeros whenever our frame was on the bus. The dash reads those bits, and on-device testing showed an intermittent front-camera fault and a missing engaged departure display. Relay the camera's exact bytes instead, on each new camera frame, with only the three hands-warn bits masked -- and only while steering. CAM_LKAS now carries the camera's LDW and LINE_NOT_VISIBLE bits so an engaged departure still reaches the dash, and its counter continues the camera's sequence at each engage edge instead of jumping by an arbitrary phase.
It counts controller frames since the last camera frame, not misses.
…arning Device testing of the byte-exact 0x440 relay still showed the v1 wrong-side signature engaged (right departure -> left flash, left -> nothing), so the dash reads departure-side bits from 0x243 as well. The engaged 0x243 is now an overlay on the camera's exact frame: openpilot writes only the torque field, the counter and the zero-angle pattern, adjusting the checksum by exactly the fields touched (a delta off the camera's own checksum, so bits outside the formula's model keep the camera's own contributions). Every other bit, defined or not, is the camera's. The dash hands warning is the camera's in both states now: relaying openpilot's steerRequired events painted an orange steering wheel for every wheel-touch and distraction alert.
The steer_required parameter on the HUD relay was dead once the camera owned the hands warning; the masks, their tests and the stale comments went with it. cam_laneinfo was a dead write -- the FSC settle gate reads the parser directly -- and the overlay now derives the counter and torque for its checksum delta from the curated bytes instead of taking them as parameters. The FRAME_RAW container signals gain CM_ comments, since no other DBC uses that construct.
v4 on-device: engaged lane-departure warnings are correct on both sides,
but openpilot could only steer while the camera saw lanes. The EPS gates
torque on the camera's line-visibility state in 0x243, and the overlay
relayed it -- the curated build had always forced it off ("they all work
just fine if set to zero"). The overlay now clears the bit and the
checksum delta pays for it; LDW and the undocumented side bits still
ride through, so the dash alerts stay correct. The curated fallback
returns to upstream's zeros for both bits.
v5 on-device: steering and lane-departure warnings are correct in both states. Two gaps left. The camera's hands warning, relayed byte-exact while engaged, tracks "LAS applying torque" rather than the driver, so the orange wheel was on nearly whenever lane lines were drawn. And with the steerRequired mapping deleted, openpilot alerts -- the turn-limit warning above all -- lost their dash channel, which the stock setup had always given them. While openpilot steers, the three hands-warn bits now carry openpilot's hold-the-wheel alert: cleared when quiet, set when steerRequired is up (the pre-branch behavior). While not steering, the camera's own warning passes through untouched.
The LAS visuals were a side effect of the passthrough: while engaged, the camera's lane lines drew on the dash and HUD alongside openpilot's own screen. Per the keep-the-alerts tradeoff, the relay now blanks LANE_LINES (LKAS disabled) whenever openpilot steers without an alert of its own, and relays the frame byte-exact while a hold-the-wheel alert is up -- the turn-limit warning keeps the rendering path the car already knows, lines and wheel together. Not steering, the camera's frame passes through untouched, flags-up windows included.
The 2 Hz hold grid keyed off the controller frame counter, whose phase has no relation to when the camera went quiet. The first hold could land up to 0.5 s past the 1 s stale window, so the dash briefly lost its lane display on a camera dropout. Key the grid to laneinfo_age_frames instead: the first hold fires 1 s after the camera's last frame, then every 0.5 s.
Comment audit: 26 lines to 9. Each invariant is now stated once, at the place a reader needs it. The EPS-gates-torque fact appears once (at the write masks) instead of three times; the LAS-vs-driver story lives at the call site; fix history and caller behavior move out of mazdacan. No code change.
The orange steering wheel is not a hands-on-wheel icon: in stock it lights while the LAS corrects back to the lane, the EPS applying torque. The DBC's HANDS_* signal names misled the relay's naming and comments. The parameter becomes steer_indicator, the masks STEER_IND_B6/B7, the comments state the observed meaning, and the DBC signals carry CM_ notes recording it. Also picks up the stale-hold watchdog switching to the age counter and trimmed comments.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
With openpilot onroad but disengaged, the car's stock LKAS correction and lane-departure display are dead. The camera still transmits
CAM_LKAS(0x243, ~16 Hz) andCAM_LANEINFO(0x440, ~2 Hz), but those frames never reach the car: both addresses sit in the Mazda TX allowlist withcheck_relay = true, and with no forward hook registered, the panda's static rule — never forward what we transmit — drops them unconditionally. The EPS sees one sender: openpilot, sending zero torque at 100 Hz.Fix
Bus ownership now follows engagement.
mazda_fwd_hookforwards the camera's 0x243 and 0x440 to the dash while openpilot is not controlling; the tx hook drops our own frames meanwhile. One sender per state; handoffs only at engage and disengage edges. "Controlling" iscontrols_allowed || controls_allowed_lateral(MADS-aware: lateral-only engagement takes the bus).check_relay(harness fault detection unchanged) but opt out of static blocking; the dynamic hook decides.create_steering_controlpreserves the camera bits of 0x243, andcreate_alert_commandre-sends the whole decodedCAM_LANEINFOframe, overriding only the hands warnings. openpilot no longer fabricatesldwalerts; the dash stays camera-driven in both states, and the car's own lane-departure setting governs. (An earlier curated signal list flashed the wrong side on device — the dash reads more than theLDW_WARN_LL/RLbits.)DISENGAGED_IDLE_STEER_TX(default True, same pattern asNO_STEER_REQ_BIT); the Mazda class sets False.Validation
test_stock_relaydrivesset_controls_allowed/set_controls_allowed_lateralthrough all four engagement combinations, asserting forward and TX for both addresses. The lateral-only row proves the lateral flag alone grants ownership.TestSteeringCommand,TestAlertCommand,TestRelayEmission,TestCamRelaySources.Open items
AI Usage
Disclaimer: GLM-5.3 by Z.ai was used to help develop, debug, and document this submission. All changes were reviewed and validated by a human.